﻿using System;
using System.Collections.Generic;
using MbUnit.Framework;
using Moq;
using ZProjectNamespaceNameZ.ZSafeParentProjectNameZ;
using DotNetNuke.Services.Cache;
using DotNetNuke.Tests.Utilities.Mocks;

namespace ZSafeProjectNameZ.Tests
{
    /// <summary>
    /// This class asserts the correct functionality of the
    /// <see cref="ViewZParentProjectNameZPresenter"/> Presenter class.
    /// </summary>
    /// <remarks>
    /// <para>
    /// The <see cref="ViewZParentProjectNameZFixture"/> class contains
    /// tests to assert the correct functionality for the
    /// <see cref="ViewZParentProjectNameZPresenter"/> Presenter and its
    /// interaction with it corresponding View
    /// (<see cref="ViewZParentProjectNameZ"/>)
    /// and Controller
    /// (<see cref="IZParentProjectNameZController"/>).
    /// </para>
    /// </remarks>
    [TestFixture]
    public class ViewZParentProjectNameZPresenter_Tests // NOTE: Changed the class name from ViewZParentProjectNameZFixture
    {
        #region Object being tested
        private ViewZParentProjectNameZPresenter _Presenter;
        #endregion

        #region Setup and Mocked objects
        #region Mocked objects
        private Mock<CachingProvider> _MockCache;
        private int _ModuleID;
        private Dictionary<string, string> _Settings;
        private Mock<IViewZParentProjectNameZ> _View;
        private Mock<IZParentProjectNameZController> _Controller;
        private List<ZParentProjectNameZInfo> _Data;
        #endregion

        #region Setup for each test
        [SetUp]
        public void Setup()
        {
            // Arrange...
            //      the module's data
            _Data = new List<ZParentProjectNameZInfo>();
            string[] expectedContent = { "First one", "Second one", "Last one" };
            for (int i = 0; i < expectedContent.Length; i++)
            {
                _Data.Add(new ZParentProjectNameZInfo() { ModuleId = _ModuleID, ItemId = i + 100, Content = expectedContent[i] });
            }
            //      the module's properties and settings
            _ModuleID = 5;
            _Settings = new Dictionary<string, string>();
            _Settings.Add("template", "");
            //      the View
            _View = new Mock<IViewZParentProjectNameZ>();
            _View.SetupAllProperties(); 
            //      the Controller
            _Controller = new Mock<IZParentProjectNameZController>();
            _Controller.Setup(self => self.GetZParentProjectNameZs(_ModuleID)).Returns(_Data);
            //      the background caching
            _MockCache = MockCachingProvider.CreateMockProvider();
            CreatePresenter();
        }
        #endregion

        #region Helper Methods
        private void CreatePresenter()
        {
            _Presenter = new ViewZParentProjectNameZPresenter(_View.Object, _Controller.Object) { ModuleId = _ModuleID, Settings = _Settings };
        }

        private void CreatePresenter(List<ZParentProjectNameZInfo> data)
        {
            _Data = data;
            _Controller = new Mock<IZParentProjectNameZController>();
            _Controller.Setup(self => self.GetZParentProjectNameZs(_ModuleID)).Returns(_Data);
            CreatePresenter();
        }
        #endregion
        #endregion

        #region Test Constructor
        /// <summary>
        /// 
        /// </summary>
        [Test]
        [Description("Ensure that the constructor checks for a non-null Controller object")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void Presenter_Constructor_Requires_Non_Null_Controller()
        {
            // Arrange (see the SetUp method)
            // Act 
            // Assert
            Assert.Throws<ArgumentNullException>(() => { _Presenter = new ViewZParentProjectNameZPresenter(_View.Object, null); });
        }

        /// <summary>
        /// 
        /// </summary>
        /// <remarks>
        /// Note that it is impossible for presenters to perform their own validation
        /// of the View before calling the base class constructor; the base constructor
        /// does not perform validation for a null View, but the base's constructor uses
        /// the View to set its Model. Attempting to use a non-null view will result in 
        /// a NullReferenceException.
        /// </remarks>
        [Test]
        [Description("Ensure that the constructor checks for a non-null View object")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void Presenter_Constructor_Requires_Non_Null_View()
        {
            // Arrange (see the SetUp method)
            // Act
            // Assert
            Assert.Throws<NullReferenceException>(() => { _Presenter = new ViewZParentProjectNameZPresenter(null); });
            Assert.Throws<NullReferenceException>(() => { _Presenter = new ViewZParentProjectNameZPresenter(null, _Controller.Object); });
        }

        /// <summary>
        /// 
        /// </summary>
        [Test]
        [Description("Ensure that the constructor calls the base class, which sets up the View's Model property")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void Presenter_Constructor_Sets_View_Model_Instance()
        {
            // Arrange (see the SetUp method)
            // Act
            _Presenter = new ViewZParentProjectNameZPresenter(_View.Object, _Controller.Object);

            // Assert
            Assert.IsNotNull(_Presenter.View.Model);
        }
        #endregion

        #region Test OnInit Event Handler
        /// <summary>
        /// 
        /// </summary>
        [Test]
        [Description("Ensure that the Presenter creates a default ZParentProjectNameZInfo instance when the Controller returns an empty list")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void Presenter_OnInit_Adds_Default_Content_When_Controller_Returns_Empty_Collection()
        {
            // Arrange (see the SetUp method)
            CreatePresenter(new List<ZParentProjectNameZInfo>());

            // Act (Raise the Initialize Event)
            _View.Raise(self => self.Initialize += null, new System.EventArgs());

            // Assert
            _Controller.VerifyAll();
            List<ZParentProjectNameZInfo> ActualList;
            ActualList = _Presenter.View.Model.ZParentProjectNameZs;
            Assert.IsNotNull(ActualList);
            Assert.AreEqual(1, ActualList.Count);

            ZParentProjectNameZInfo ActualInfoInstance;
            ActualInfoInstance = ActualList[0];
            Assert.AreEqual(_ModuleID, ActualInfoInstance.ModuleId);
            Assert.AreEqual("View.Content", ActualInfoInstance.Content);
            Assert.AreEqual(0, ActualInfoInstance.CreatedByUser);
            Assert.AreEqual(0, ActualInfoInstance.ItemId);
        }

        [Test]
        [Description("Ensure that the Presenter populates the View's Model property with an existing collection of ZParentProjectNameZInfo objects")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void Presenter_OnInit_Gets_Existing_Content_From_Controller_GetZParentProjectNameZs()
        {
            // Arrange (see the SetUp method)
            // Act (Raise the Initialize Event)
            _View.Raise(self => self.Initialize += null, new System.EventArgs());

            // Assert
            _Controller.VerifyAll();
            List<ZParentProjectNameZInfo> ActualList;
            ActualList = _Presenter.View.Model.ZParentProjectNameZs;
            Assert.IsNotNull(ActualList);
            Assert.AreEqual(_Data.Count, ActualList.Count);

            for (int i = 0; i < ActualList.Count; i++)
            {
            ZParentProjectNameZInfo ActualFirstInfoInstance;
                ActualFirstInfoInstance = ActualList[i];
                Assert.AreEqual(_Data[i].ModuleId, ActualFirstInfoInstance.ModuleId);
                Assert.AreEqual(_Data[i].Content, ActualFirstInfoInstance.Content);
                Assert.AreEqual(_Data[i].CreatedByUser, ActualFirstInfoInstance.CreatedByUser);
                Assert.AreEqual(_Data[i].ItemId, ActualFirstInfoInstance.ItemId);
            }
        }

        [Test]
        [Description("Ensure that the Presenter applies the 'template' setting to format the ZParentProjectNameZInfo's Content and places it in the DisplayContent property")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void Presenter_OnInit_Applies_Template_To_Format_ZParentProjectNameZInfo_DisplayContent()
        {
            // Arrange (see the SetUp method)
            _Settings["template"] = "[CONTENT]<br /><span>on [CREATEDDATE] by [CREATEDBYUSERNAME]";
            CreatePresenter();

            // Act (Raise the Initialize Event)
            _View.Raise(self => self.Initialize += null, new System.EventArgs());

            // Assert
            _Controller.VerifyAll();
            List<ZParentProjectNameZInfo> ActualList = _Presenter.View.Model.ZParentProjectNameZs;
            foreach (ZParentProjectNameZInfo item in ActualList)
            {
                Assert.Contains(item.DisplayContent, item.Content);
                Assert.Contains(item.DisplayContent, item.CreatedDate.ToString());
                Assert.Contains(item.DisplayContent, item.CreatedByUser.ToString());
            }
        }

        /// <summary>
        /// 
        /// </summary>
        [Test]
        [Description("Ensure that the Presenter stores the ZParentProjectNameZInfo's Content value into the DisplayContent property whenever the 'template' setting is an empty string")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void Presenter_OnInit_Sets_ZParentProjectNameZInfo_DisplayContent_To_Content_When_Template_Is_Empty()
        {
            // Arrange (see the SetUp method)
            // Act (Raise the Initialize Event)
            _View.Raise(self => self.Initialize += null, new System.EventArgs());

            // Assert
            _Controller.VerifyAll();
            List<ZParentProjectNameZInfo> ActualList = _Presenter.View.Model.ZParentProjectNameZs;
            foreach (ZParentProjectNameZInfo item in ActualList)
            {
                Assert.Contains(item.DisplayContent, item.Content);
            }
        } 

        /// <summary>
        /// 
        /// </summary>
        [Test]
        [Description("Ensure that the Presenter stores the ZParentProjectNameZInfo's Content value into the DisplayContent property whenever the 'template' setting has only whitespace")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void Presenter_OnInit_Sets_ZParentProjectNameZInfo_DisplayContent_To_Content_When_Template_Is_All_Whitespace()
        {
            // Arrange (see the SetUp method)
            _Settings["template"] = "  ";
            CreatePresenter();

            // Act (Raise the Initialize Event)
            _View.Raise(self => self.Initialize += null, new System.EventArgs());

            // Assert
            _Controller.VerifyAll();
            List<ZParentProjectNameZInfo> ActualList = _Presenter.View.Model.ZParentProjectNameZs;
            for (int i = 0; i < ActualList.Count; i++)
            {
                Assert.AreEqual(_Data[i].Content, ActualList[i].Content);
                Assert.AreEqual(_Data[i].DisplayContent, ActualList[i].Content);
            }
        } 
        #endregion
   } // end of class
} // end of namespace
